﻿using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Text.RegularExpressions;
using WorkFlow.Data;
using WorkFlow.Data.Model;

namespace WorkFlow
{
    [Route("api/[controller]/[action]")]
    [ApiController]
    public class WorkFlowController : ControllerBase
    {
        SqlHelper _sqlHelper;
        DataManager _DataManager;
        WorkFlowTool _WorkFlowTool;
        public WorkFlowController(SqlHelper sqlHelper, DataManager dataManager,WorkFlowTool workFlowTool)
        {
            _sqlHelper = sqlHelper;
            _DataManager = dataManager;
            _WorkFlowTool = workFlowTool;
        }
        [HttpPost]
        public bool RunWorkFlow(dynamic parameters)
        {
            return RunWorkFlowByString(parameters.ToString());
        }

        [HttpGet]
        public bool RunWorkFlowByString(string parameters)
        {
            bool result = false;
            try
            {
                Dictionary<string, string> dict = DeserializeJson<Dictionary<string, string>>(parameters);
                string name = dict["WorkFlowName"];
                string user = dict["InitUser"];
                string sql = $"insert into workflowinfo values('0','{name}','{user}','0','','','{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}','')";
                string message;
                string id;
                int count = _sqlHelper.ExecuteNonQueryAndID(sql, out id, out message);
                if (count == 1)
                {
                    // Update main task status to running
                    sql = $"update workflowinfo set Status='1' where ID='{id}'";
                    _sqlHelper.ExecuteNonQuery(sql, out message);
                    // Automation complete Start node
                    WorkFlowFile startWorkFlowFile = _WorkFlowTool.GetStarStepIDbyWorkFlowName(name);
                    sql = $"insert into workflowdetail value('0','{id}','-1','{startWorkFlowFile.StepID}','Start','{user}','2','','','0','0','{DateTime.Now.ToString(WorkFlowTool.timeStyle)}','')";
                    count = _sqlHelper.ExecuteNonQueryAndID(sql, out id, out message);
                    // 保存所有参数
                    DataTable dataTable = new DataTable();
                    sql = $"select * from parameter where DetailID='{id}'";
                    dataTable = _sqlHelper.myDataSet(sql).Tables[0];
                    foreach (string key in dict.Keys)
                    {
                        DataRow newRow = dataTable.NewRow();
                        newRow["ID"] = "0";
                        newRow["DetailID"] = id;
                        newRow["Name"] = key;
                        newRow["Value"] = dict[key];
                        dataTable.Rows.Add(newRow);
                    }
                    count = _sqlHelper.SaveDataTable(sql, dataTable, out message);
                    if (count > 0)
                        result = true;
                    else
                    {
                        LogHelper.WriteLog("RunWorkFlow:Step2:" + message);
                    }

                }
                else
                    LogHelper.WriteLog("RunWorkFlow:Step2:" + message);
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex);
            }
            return result;
        }

        [HttpPost]
        public bool TaskIsComplete(dynamic parameters)
        {
            return TaskIsCompleteByString(parameters.ToString());
        }

        [HttpGet]
        public bool TaskIsCompleteByString(string parameters)
        {
            try
            {
                Dictionary<string, string> dict = DeserializeJson<Dictionary<string, string>>(parameters);
                string detailID = dict["WorkFlowDetailID"].ToString();
                string result = dict["WorkFlowTaskResult"].ToString();
                string user = "";
                if (dict.ContainsKey("User"))
                {
                    user = dict["User"].ToString();
                }
                string message = "";
                if (dict.ContainsKey("Message"))
                {
                    message = dict["Message"].ToString();
                }
                string status = "";
                if (result.ToLower() == "1" || result.ToLower() == "true")
                {
                    status = "2";
                }
                else
                {
                    status = "3";
                }
                string sql = $"update workflowdetail set User='{user}',Status='{status}'," +
                    $"Message='{message}',CompleteTime='{DateTime.Now.ToString(WorkFlowTool.timeStyle)}'" +
                    $" where ID='{detailID}'";
                string outmessage;
                int count = _sqlHelper.ExecuteNonQuery(sql, out outmessage);
                if (count > 0)
                {
                    // Get current task node
                    WorkFlowFile currentWorkFlowFile = _WorkFlowTool.GetCurrentTaskNode(detailID);
                    // Add out parameters
                    sql = $"select * from parameter where DetailID='{detailID}'";
                    DataTable parameterDT = new DataTable();
                    parameterDT = _sqlHelper.myDataSet(sql).Tables[0];
                    foreach (Parameter parameter in currentWorkFlowFile.Config.OutParameters)
                    {
                        string newValue = "";
                        // If the out value have not special format then the value of should be inserted come from Dictionary
                        if (parameter.Value == "")
                        {
                            if (dict.ContainsKey(parameter.Name))
                            {
                                newValue = dict[parameter.Name];
                            }
                        }
                        // If the workflow out value is come from DB then get newValue from DB
                        else if (Regex.IsMatch(parameter.Value, "^\\{.*?\\}$"))
                        {
                            DataRow[] dataRows = parameterDT.Select($"Name='{parameter.Name}'");
                            if (dataRows.Length > 0)
                            {
                                newValue = dataRows[0]["Value"].ToString();
                            }
                        }
                        // If other format then the newValue is workflow out value
                        else
                        {
                            newValue = parameter.Value;
                        }
                        DataRow[] rows = parameterDT.Select($"Name='{parameter.Name}'");
                        // If DB have exist the name then update the value 
                        if (rows.Length > 0)
                        {
                            rows[0][parameter.Name] = newValue;
                        }
                        // If DB have not exist the parameter name then add the name-value
                        else
                        {
                            DataRow newRow = parameterDT.NewRow();
                            newRow["ID"] = "0";
                            newRow["DetailID"] = detailID;
                            newRow["Name"] = parameter.Name;
                            newRow["Value"] = newValue;
                            parameterDT.Rows.Add(newRow);
                        }
                        _sqlHelper.SaveDataTable(sql, parameterDT, out outmessage);
                    }
                    return true;
                }
                return false;
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex);
                return false;
            }
        }

        [HttpGet]
        public List<WorkFlowDetail> GetAllViews()
        {
            List<WorkFlowDetail> workFlowDetails = _DataManager.GetAllWorkFlowDetailView();
            return workFlowDetails;
        }

        [HttpGet]
        public WorkFlowFile GetViewConfig(string detailID)
        {
            WorkFlowDetail workFlowDetail = _DataManager.GetWorkFlowDetailByID(detailID);
            WorkFlowFile workFlowFile = _WorkFlowTool.GetWorkFlowFileByStepID(workFlowDetail.WorkFlowName, workFlowDetail.StepID);
            return workFlowFile;
        }

        [HttpGet]
        public List<ParameterEntity> GetParameterByDetailID(string detailID)
        {
            List<ParameterEntity> parameters = _WorkFlowTool.GetInParametersByDetailID(detailID);
            return parameters;
        }

        public static string SerializeJson<T>(T obj, int indentation = 0, char indentchar = ' ')
        {
            StringWriter writer = new StringWriter();
            JsonTextWriter jsoonWriter = new JsonTextWriter(writer)
            {
                Formatting = Formatting.Indented,
                Indentation = indentation,
                IndentChar = indentchar
            };
            JsonSerializer serializer = new JsonSerializer();
            serializer.Serialize(jsoonWriter, obj);
            return writer.ToString();
        }

        public static T DeserializeJson<T>(string json)
        {
            return JsonConvert.DeserializeObject<T>(json);
        }
    }
}
